#include <fstream>
#include <iostream>
#include <sstream>

#include "Locations.h"

using namespace std;

Locations::Locations()
{
    //ctor
    string input;
    cout << "SpacerSeeker-env v1.0" << endl;
    cout << "please enter location of spacers file (fasta format):  ";
    getline(cin, input);
    while (!file_exists(input))
    {
        cout << "designated spacers file does not exist, please re-enter spacers file:  ";
        getline(cin, input);
    }
    spacer_loc = input;
    cout << "input contigs? (Y/N):  ";
    getline(cin, input);
    if (input == "Y" ^ input == "y")
    {
        check_contigs = true;
        cout << "please enter location of contigs file (fasta format):  ";
        getline(cin, input);
        while (!file_exists(input))
        {
            cout << "designated contigs file does not exist, please re-enter contigs file:  ";
            getline(cin, input);
        }
        contig_loc = input;
    }
    else
    {
        check_contigs = false;
    }
    cout << "use RefSeq genomes? (Y/N):  ";
    getline(cin, input);
    if (input == "Y" ^ input == "y")
    {
        check_genomes = true;
        cout << "please enter directory containing genomes:  ";
        getline(cin, input);
        virus_dir = input;
        cout << "please enter file of virus names:  ";
        getline(cin, input);
        virus_fof = input;
        while(!file_exists(virus_dir+virus_fof))
        {
            cout << "please enter directory containing genomes:  ";
            getline(cin, input);
            virus_dir = input;
            cout << "please enter file of virus names:  ";
            getline(cin, input);
            virus_fof = input;
        }
    }
    else
    {
        check_genomes = false;
    }
    cout << "please enter results prefix:  ";
    getline(cin, input);
    results_dir = input;
    cout << "use default params (Y/N):  ";
    getline(cin, input);
    if (input == "Y" ^ input == "y")
    {
        seed = 10;
        ident = .8;
        min_seq_len = 20;
    }
    else
    {
        while (true)
        {
            cout << "please enter k-size:  ";
            getline(cin, input);
            stringstream myStream(input);
            if (myStream >> seed)
            {
                break;
            }
            cout << "invalid k-size, ";
        }
        while (true)
        {
            cout << "please enter min identity (0-1):  ";
            getline(cin, input);
            stringstream myStream(input);
            if (myStream >> ident)
            {
                break;
            }
            cout << "invalid min identity, " << endl;
        }
        while (true)
        {
            cout << "please enter min sequence length:  ";
            getline(cin, input);
            stringstream myStream(input);
            if (myStream >> min_seq_len)
            {
                break;
            }
            cout << "invalid length, ";
        }
    }
}

Locations::~Locations()
{
    //dtor
}

void Locations::get_spacers(vector<Sequence> &seqs)
{
    get_from_multifasta(seqs, spacer_loc, "spacer");
}

void Locations::get_virus_contigs(vector<Sequence> &seqs)
{
    get_from_multifasta(seqs, contig_loc, "contig");
}

void Locations::get_virus_genomes(vector<Sequence> &seqs)
{
    get_fastas_from_dir(seqs, virus_dir, virus_fof, "genome");
}

void Locations::get_from_multifasta(vector<Sequence> &seqs, string loc, string type)
{
    fstream in2;
    in2.open(loc.c_str());
    if (in2.is_open()==false)
    {
        cout << "Input file not found" << endl;
    }
    while (in2.peek() != EOF)
    {
        //get header
        string header;
        getline(in2, header);

        //get sequence
        string seq;
        getline(in2, seq);
        while (in2.peek() != '>' && in2.peek() != EOF)
        {
            string more_seq;
            getline(in2, more_seq);
            seq += more_seq;
        }
        if (seq.length()>min_seq_len)
        {
            seqs.push_back(Sequence(header, seq, type));
        }
    }
}

void Locations::get_fastas_from_dir(vector<Sequence> &seqs, string genomes_dir, string genomes_list, string type)
{
    ifstream find;
    find.open(genomes_list.c_str());
    if (find.is_open()==false)
    {
        cout<<"no such file 0 files"<<endl;
    }
    vector<string> file_names;
    while (find.peek()!=EOF)
    {
        string file_name;
        getline(find, file_name);
        file_name = genomes_dir+file_name;
        file_names.push_back(file_name);
    }
    find.clear();
    find.close();

    ifstream in;
    for (int i = 0; i < file_names.size(); i++)
    {
        in.open(file_names[i].c_str());
        if (in.is_open()==false)
        {
            cout<<"file not found"<<endl;
            continue;
        }
        char junk [1000];
        in.getline(junk,1000,'\n');
        int length = 0;
        while(in.peek()!=EOF)
        {
            in>> junk[0];
            length++;
        }
        in.clear();
        in.close();
        in.open(file_names[i].c_str());
        string header;
        getline(in, header);
        int n = 0;
        string seq;
        while (n<length)
        {
            char save;
            in >> save;
            seq+=save;
            n++;
        }
        in.clear();
        in.close();
        if (seq.length() >min_seq_len)
        {
            seqs.push_back(Sequence(header, seq, type));
        }
    }
}

bool Locations::file_exists(string file)
{
    fstream in;
    in.open(file.c_str());
    if (in.is_open())
    {
        in.close();
        return true;
    }
    else
    {
        return false;
    }
}
